home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
CUGUK
/
UTIL_SRC
/
C016.ZIP
/
CALC
/
HOC.C
next >
Wrap
Text File
|
1990-01-19
|
11KB
|
459 lines
# line 17 "hoc.y"
/*********************** self documentation **********************/
char *sdoc = "\
\n\
HOC - hoc [-] \n\
\n\
hoc is an enhanced version 3 of Kernighan and Pike's calculator \n\
You exit by typing a ctrl-D. It works like so: \n\
hoc \n\
3 + 4 \n\
7 \n\
3^4 \n\
81 \n\
sqrt(#) \n\
9 \n\
sin(PI/6) \n\
.5 \n\
3e-3 * # \n\
0.075 \n\
c = 5687; tmin = 1.2 \n\
c * tmin \n\
6824.4 \n\
^D \n\
# is the symbol for the last value printed. \n\
functions and constants: \n\
\n\
DEG (deg/radian), E, GAMMA (Euler), PHI (golden), PI \n\
abs, acos, asin, atan, atan2, ceil, cos, cosh, exp, floor, \n\
gamma, hypot, int, j0, j1, jn, log, log10, pow, rand, sin, \n\
sinh, sqrt, srand, tan, tanh, y0, y1, yn \n\
";
/*****************************************************************/
#include "hoc.h"
#include "su.h"
#include "jc.h"
extern double floor(), Pow();
double lastno; /* last printed value */
# line 65 "hoc.y"
typedef union {
double val; /* actual value */
Symbol *sym; /* symbol table pointer */
} YYSTYPE;
# define NUMBER 257
# define ENDLIST 258
# define CON 259
# define VAR 260
# define BLTIN 261
# define BLTIN2 262
# define BLTIN0 263
# define UNDEF 264
# define UNARYMINUS 265
# define UNARYPLUS 266
#define yyclearin yychar = -1
#define yyerrok yyerrflag = 0
extern int yychar;
extern short yyerrflag;
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 150
#endif
YYSTYPE yylval, yyval;
# define YYERRCODE 256
# line 118 "hoc.y"
/* end of grammar */
#include <signal.h>
#include <setjmp.h>
jmp_buf begin;
int lineno = 0;
main(argc, argv) /* hoc3 */
int argc;
char *argv[];
Begin
int fpecatch(); /* floating point error catcher */
/* Set up standard SU args */
xargc = argc; xargv = argv;
/* Code begins - check usage */
If xargc != 1 Do
selfdoc();
Endif
init();
setjmp(begin);
signal(SIGFPE, fpecatch);
yyparse();
End
execerror(s, t) /* recover from runtime error */
register char *s, *t;
Begin
warning(s, t);
longjmp(begin, 0);
End
int fpecatch() /* catch floating point exceptions */
Begin
execerror("floating point exception", (char *) 0);
End
int yylex()
Begin
register int c;
While (c = getchar()) == ' ' || c == '\t' Do
;
Endwhile
If c == EOF Do /* archaic yyparse uses 0 for end_of_file */
Return 0;
Endif
If c == '.' || isdigit(c) Do /* number */
ungetc(c, stdin);
scanf("%lf", &yylval.val);
Return NUMBER;
Endif
If c == '#' Do
yylval.val = lastno;
Return NUMBER;
Endif
If isalpha(c) Do
Symbol *s;
char sbuf[100], *p = sbuf;
Loop
*p++ = c;
Exitif( (c = getchar()) == EOF || !isalnum(c) );
Endloop
ungetc(c, stdin);
*p = '\0';
If (s = lookup(sbuf)) == 0 Do
s = install(sbuf, UNDEF, 0.0);
Endif
yylval.sym = s;
Return s->type == UNDEF ? VAR : s->type;
Endif
If c == '\n' Do
lineno++;
Endif
If c == '\n' || c == ';' Do
Return ENDLIST;
Endif
Return c;
End
yyerror(s) /* called for yacc syntax error */
register char *s;
Begin
warning(s, (char *) 0 );
End
warning(s, t) /* print warning message */
register char *s, *t;
Begin
fprintf(stderr, "%s: %s", xargv[0], s);
If t Do
fprintf(stderr, "%s", t);
Endif
fprintf(stderr, " near line %d\n", lineno);
End
short yyexca[] ={
-1, 1,
0, -1,
-2, 0,
};
# define YYNPROD 24
# define YYLAST 233
short yyact[]={
12, 23, 15, 14, 22, 13, 25, 12, 24, 43,
14, 21, 13, 28, 1, 27, 19, 17, 21, 18,
26, 20, 48, 19, 17, 21, 18, 30, 20, 3,
19, 17, 46, 18, 21, 20, 0, 0, 45, 19,
17, 21, 18, 0, 20, 44, 19, 17, 21, 18,
21, 20, 0, 19, 17, 19, 18, 0, 20, 0,
20, 0, 0, 0, 0, 0, 0, 0, 22, 0,
0, 0, 0, 0, 4, 22, 0, 0, 0, 0,
0, 0, 22, 0, 0, 0, 0, 29, 31, 32,
0, 22, 33, 34, 35, 36, 37, 38, 22, 39,
40, 41, 42, 0, 0, 22, 0, 22, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 47, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 5, 8, 2, 6,
7, 9, 10, 11, 8, 0, 6, 7, 9, 10,
11, 0, 16 };
short yypact[]={
-1000, -40,-1000,-256, -26,-257, -53, -55,-1000, -20,
-25, -27, -33, -33, -33,-1000,-1000, -33, -33, -33,
-33, -33, -33,-1000, -33, -33, -33, -33, -32, 4,
-1000, -90, -90, 13, 13, -90, -90, -90, -90, 11,
11, -3, -12,-1000,-1000,-1000, -33, -19,-1000 };
short yypgo[]={
0, 74, 27, 14 };
short yyr1[]={
0, 3, 3, 3, 3, 3, 2, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1 };
short yyr2[]={
0, 0, 2, 3, 3, 3, 3, 3, 1, 1,
1, 4, 6, 3, 1, 3, 3, 3, 3, 3,
3, 3, 2, 2 };
short yychk[]={
-1000, -3, 258, -2, -1, 256, 259, 260, 257, 261,
262, 263, 40, 45, 43, 258, 258, 43, 45, 42,
47, 37, 94, 258, 61, 61, 40, 40, 40, -1,
-2, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 41, 41, 41, 44, -1, 41 };
short yydef[]={
1, -2, 2, 14, 0, 0, 9, 10, 8, 0,
0, 0, 0, 0, 0, 3, 4, 0, 0, 0,
0, 0, 0, 5, 0, 0, 0, 0, 0, 0,
14, 22, 23, 15, 16, 17, 18, 19, 20, 6,
7, 0, 0, 13, 21, 11, 0, 0, 12 };
#
# define YYFLAG -1000
# define YYERROR goto yyerrlab
# define YYACCEPT return(0)
# define YYABORT return(1)
/* parser for yacc output */
#ifdef YYDEBUG
int yydebug = 0; /* 1 for debugging */
#endif
YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */
int yychar = -1; /* current input token number */
int yynerrs = 0; /* number of errors */
short yyerrflag = 0; /* error recovery flag */
yyparse() {
short yys[YYMAXDEPTH];
short yyj, yym;
register YYSTYPE *yypvt;
register short yystate, *yyps, yyn;
register YYSTYPE *yypv;
register short *yyxi;
yystate = 0;
yychar = -1;
yynerrs = 0;
yyerrflag = 0;
yyps= &yys[-1];
yypv= &yyv[-1];
yystack: /* put a state and value onto the stack */
#ifdef YYDEBUG
if( yydebug ) printf( "state %d, char 0%o\n", yystate, yychar );
#endif
if( ++yyps> &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); }
*yyps = yystate;
++yypv;
*yypv = yyval;
yynewstate:
yyn = yypact[yystate];
if( yyn<= YYFLAG ) goto yydefault; /* simple state */
if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0;
if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault;
if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */
yychar = -1;
yyval = yylval;
yystate = yyn;
if( yyerrflag > 0 ) --yyerrflag;
goto yystack;
}
yydefault:
/* default state action */
if( (yyn=yydef[yystate]) == -2 ) {
if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0;
/* look through exception table */
for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */
while( *(yyxi+=2) >= 0 ){
if( *yyxi == yychar ) break;
}
if( (yyn = yyxi[1]) < 0 ) return(0); /* accept */
}
if( yyn == 0 ){ /* error */
/* error ... attempt to resume parsing */
switch( yyerrflag ){
case 0: /* brand new error */
yyerror( "syntax error" );
yyerrlab:
++yynerrs;
case 1:
case 2: /* incompletely recovered error ... try again */
yyerrflag = 3;
/* find a state where "error" is a legal shift action */
while ( yyps >= yys ) {
yyn = yypact[*yyps] + YYERRCODE;
if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){
yystate = yyact[yyn]; /* simulate a shift of "error" */
goto yystack;
}
yyn = yypact[*yyps];
/* the current yyps has no shift onn "error", pop stack */
#ifdef YYDEBUG
if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] );
#endif
--yyps;
--yypv;
}
/* there is no state on the stack with an error shift ... abort */
yyabort:
return(1);
case 3: /* no shift yet; clobber input char */
#ifdef YYDEBUG
if( yydebug ) printf( "error recovery discards char %d\n", yychar );
#endif
if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */
yychar = -1;
goto yynewstate; /* try again in the same state */
}
}
/* reduction by production yyn */
#ifdef YYDEBUG
if( yydebug ) printf("reduce %d\n",yyn);
#endif
yyps -= yyr2[yyn];
yypvt = yypv;
yypv -= yyr2[yyn];
yyval = yypv[1];
yym=yyn;
/* consult goto table to find next state */
yyn = yyr1[yyn];
yyj = yypgo[yyn] + *yyps + 1;
if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]];
switch(yym){
case 4:
# line 81 "hoc.y"
{ lastno = yypvt[-1].val; printf("\t%.8g\n", yypvt[-1].val); } break;
case 5:
# line 82 "hoc.y"
{ yyerrok; } break;
case 6:
# line 84 "hoc.y"
{ execerror("can't assign to constant: ", yypvt[-2].sym->name); } break;
case 7:
# line 85 "hoc.y"
{ yyval.val = yypvt[-2].sym->u.val = yypvt[-0].val; yypvt[-2].sym->type = VAR; } break;
case 8:
# line 87 "hoc.y"
{ yyval.val = yypvt[-0].val; } break;
case 9:
# line 88 "hoc.y"
{ yyval.val = yypvt[-0].sym->u.val; } break;
case 10:
# line 89 "hoc.y"
{
If yypvt[-0].sym->type == UNDEF Do
execerror("undefined variable: ", yypvt[-0].sym->name);
Endif
yyval.val = yypvt[-0].sym->u.val; } break;
case 11:
# line 94 "hoc.y"
{ yyval.val = (*(yypvt[-3].sym->u.ptr))(yypvt[-1].val); } break;
case 12:
# line 95 "hoc.y"
{
yyval.val = (*(yypvt[-5].sym->u.ptr))(yypvt[-3].val, yypvt[-1].val); } break;
case 13:
# line 97 "hoc.y"
{ yyval.val = (*(yypvt[-2].sym->u.ptr))(); } break;
case 15:
# line 99 "hoc.y"
{ yyval.val = yypvt[-2].val + yypvt[-0].val; } break;
case 16:
# line 100 "hoc.y"
{ yyval.val = yypvt[-2].val - yypvt[-0].val; } break;
case 17:
# line 101 "hoc.y"
{ yyval.val = yypvt[-2].val * yypvt[-0].val; } break;
case 18:
# line 102 "hoc.y"
{
If yypvt[-0].val == 0.0 Do
execerror("division by zero", "");
Endif
yyval.val = yypvt[-2].val / yypvt[-0].val; } break;
case 19:
# line 107 "hoc.y"
{ /* definition as per Knuth, v1 */
If yypvt[-0].val == 0.0 Do
yyval.val = yypvt[-2].val;
Elsedo
yyval.val = yypvt[-2].val - yypvt[-0].val * floor(yypvt[-2].val / yypvt[-0].val);
Endif } break;
case 20:
# line 113 "hoc.y"
{ yyval.val = Pow(yypvt[-2].val, yypvt[-0].val); } break;
case 21:
# line 114 "hoc.y"
{ yyval.val = yypvt[-1].val ; } break;
case 22:
# line 115 "hoc.y"
{ yyval.val = -yypvt[-0].val; } break;
case 23:
# line 116 "hoc.y"
{ yyval.val = yypvt[-0].val; } break;
}
goto yystack; /* stack new state and value */
}